package com.shu.logsearch.jsch.core;

import com.jcraft.jsch.*;
import com.shu.logsearch.jsch.model.RemoteServerConfig;
import com.shu.logsearch.util.CloseUtil;
import lombok.Data;
import org.apache.tika.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * 基于jsch的远程服务器连接工具（支持跳板机）
 *
 * @author Tree Cai
 * @date 2019/7/2
 */
@Data
@Component
public class Xshell {
    private Logger logger = LoggerFactory.getLogger(this.getClass());


    /**
     * 默认指向sshSession，当isJumpServer为true时，指向destinationSession
     */
    private Session session = null;
    /**
     * 服务器的会话
     */
    private Session sshSession = null;
    /**
     * 当isJumpServer为true时，目标服务器的会话
     */
    private Session destinationSession = null;
    /**
     * ftp管道
     */
    private ChannelSftp sftp = null;

    /**
     * 连接服务器，开启sftp
     *
     * @return
     */
    public void connect(RemoteServerConfig remoteServerConfig) {
        JSch jsch = new JSch();
        logger.info("--->session连接开始>>>>>");
        if (!remoteServerConfig.checkProperties())
            return;
        try {
            sshSession = jsch.getSession(remoteServerConfig.getUserName(), remoteServerConfig.getHost(), remoteServerConfig.getPort());
            sshSession.setPassword(remoteServerConfig.getPassword());
            Properties sshConfig = new Properties();
            sshConfig.put("StrictHostKeyChecking", "no");
            sshConfig.put("PreferredAuthentications",
                    "password,keyboard-interactive");
            sshSession.setConfig(sshConfig);
            sshSession.connect();
            session = sshSession;
            if (remoteServerConfig.isJumpServer()) {
                //此处开始为端口映射到本地的部分
                sshSession.setPortForwardingL(remoteServerConfig.getForwardLocalPort(), remoteServerConfig.getDestinationHost(), remoteServerConfig.getDestinationPort());
                //完成上诉映射之后，即可通过本地端口连接了
                destinationSession = jsch.getSession(remoteServerConfig.getDestinationUserName(), "127.0.0.1", remoteServerConfig.getForwardLocalPort());
                Properties remoteCfg = new Properties();
                remoteCfg.put("StrictHostKeyChecking", "no");
                remoteCfg.put("PreferredAuthentications",
                        "password,keyboard-interactive");
                destinationSession.setConfig(remoteCfg);
                destinationSession.setPassword(remoteServerConfig.getDestinationPassword());
                destinationSession.connect();
                session = destinationSession;
            }
            logger.info("session连接成功！！！");
            logger.info("--->sftp连接开始>>>>>");
            sftp = (ChannelSftp) session.openChannel("sftp");
            sftp.connect();
            logger.info("sftp连接成功！！！");
        } catch (JSchException e) {
            logger.error("连接异常！！！");
            e.printStackTrace();
        }
    }

    /**
     * 执行单句命令行
     *
     * @param command
     * @param resultEncoding
     * @return
     */
    public String execCommand(String command, String resultEncoding) throws JSchException, IOException {
        if (StringUtils.isEmpty(command))
            return null;
        if (StringUtils.isEmpty(resultEncoding))
            resultEncoding = "UTF-8";
        ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
        InputStream inputStream = channelExec.getInputStream();
        channelExec.setCommand(command);
        channelExec.setErrStream(System.err);
        channelExec.connect();
        String result = IOUtils.toString(inputStream, resultEncoding);
        channelExec.disconnect();
        return result;
    }

    /**
     * 断开服务器连接
     */
    public void disConnect() {
        CloseUtil.disConnect(session, "session");
        CloseUtil.disConnect(sshSession, "sshSession");
        CloseUtil.disConnect(destinationSession, "destinationSession");
        CloseUtil.disConnect(sftp, "sftp");

    }



    @PostConstruct
    public void init() {
        logger.info("--->开始初始化XShell>>>>>");
//        connect();
    }

    @PreDestroy
    public void destory() {
        logger.info("--->开始销毁XShell>>>>>");
//        disConnect();
    }


}
